//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package io.paperdb;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer;
import de.javakaffee.kryoserializers.ArraysAsListSerializer;
import de.javakaffee.kryoserializers.SynchronizedCollectionsSerializer;
import de.javakaffee.kryoserializers.UUIDSerializer;
import de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer;
import io.paperdb.serializer.NoArgCollectionSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import ohos.app.Context;
import org.objenesis.strategy.StdInstantiatorStrategy;

public class DbStoragePlainFile implements Storage {
    private final Context mContext;
    private final String mDbName;
    private final HashMap<Class, Serializer> mCustomSerializers;
    private String mFilesDir;
    private boolean mPaperDirIsCreated;
    private final ThreadLocal<Kryo> mKryo = new ThreadLocal<Kryo>() {
        protected Kryo initialValue() {
            return DbStoragePlainFile.this.createKryoInstance();
        }
    };

    private Kryo getKryo() {
        return (Kryo)this.mKryo.get();
    }

    private Kryo createKryoInstance() {
        Kryo kryo = new Kryo();
        kryo.register(PaperTable.class);
        kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
        kryo.setReferences(false);
        kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer());
        UnmodifiableCollectionsSerializer.registerSerializers(kryo);
        SynchronizedCollectionsSerializer.registerSerializers(kryo);
        kryo.addDefaultSerializer((new ArrayList()).subList(0, 0).getClass(), new NoArgCollectionSerializer());
        kryo.addDefaultSerializer((new LinkedList()).subList(0, 0).getClass(), new NoArgCollectionSerializer());
        kryo.register(UUID.class, new UUIDSerializer());
        Iterator var2 = this.mCustomSerializers.keySet().iterator();

        while(var2.hasNext()) {
            Class<?> clazz = (Class)var2.next();
            kryo.register(clazz, (Serializer)this.mCustomSerializers.get(clazz));
        }

        kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
        return kryo;
    }

    public DbStoragePlainFile(Context context, String dbName, HashMap<Class, Serializer> serializers) {
        this.mContext = context;
        this.mDbName = dbName;
        this.mCustomSerializers = serializers;
    }

    public synchronized void destroy() {
        this.assertInit();
        String dbPath = this.getDbPath(this.mContext, this.mDbName);
        if (!deleteDirectory(dbPath)) {
            System.out.println("paperdb"+ "Couldn't delete Paper dir " + dbPath);
        }

        this.mPaperDirIsCreated = false;
    }

    public synchronized <E> void insert(String key, E value) {
        this.assertInit();
        PaperTable<E> paperTable = new PaperTable(value);
        File originalFile = this.getOriginalFile(key);
        File backupFile = this.makeBackupFile(originalFile);
        if (originalFile.exists()) {
            if (!backupFile.exists()) {
                if (!originalFile.renameTo(backupFile)) {
                    throw new PaperDbException("Couldn't rename file " + originalFile + " to backup file " + backupFile);
                }
            } else {
                originalFile.delete();
            }
        }

        this.writeTableFile(key, paperTable, originalFile, backupFile);
    }

    public synchronized <E> E select(String key) {
        this.assertInit();
        File originalFile = this.getOriginalFile(key);
        File backupFile = this.makeBackupFile(originalFile);
        if (backupFile.exists()) {
            originalFile.delete();
            backupFile.renameTo(originalFile);
        }

        return !this.exist(key) ? null : this.readTableFile(key, originalFile);
    }

    public synchronized boolean exist(String key) {
        this.assertInit();
        File originalFile = this.getOriginalFile(key);
        return originalFile.exists();
    }

    public synchronized long lastModified(String key) {
        this.assertInit();
        File originalFile = this.getOriginalFile(key);
        return originalFile.exists() ? originalFile.lastModified() : -1L;
    }

    public List<String> getAllKeys() {
        this.assertInit();
        File bookFolder = new File(this.mFilesDir);
        String[] names = bookFolder.list();
        if (names == null) {
            return new ArrayList();
        } else {
            for(int i = 0; i < names.length; ++i) {
                names[i] = names[i].replace(".pt", "");
            }

            return Arrays.asList(names);
        }
    }

    public synchronized void deleteIfExists(String key) {
        this.assertInit();
        File originalFile = this.getOriginalFile(key);
        if (originalFile.exists()) {
            boolean deleted = originalFile.delete();
            if (!deleted) {
                throw new PaperDbException("Couldn't delete file " + originalFile + " for table " + key);
            }
        }
    }

    public void setLogLevel(int level) {
        com.esotericsoftware.minlog.Log.set(level);
    }

    private File getOriginalFile(String key) {
        String tablePath = this.mFilesDir + File.separator + key + ".pt";
        return new File(tablePath);
    }

    private <E> void writeTableFile(String key, PaperTable<E> paperTable, File originalFile, File backupFile) {
        try {
            FileOutputStream fileStream = new FileOutputStream(originalFile);
            Output kryoOutput = new Output(fileStream);
            this.getKryo().writeObject(kryoOutput, paperTable);
            kryoOutput.flush();
            fileStream.flush();
            sync(fileStream);
            kryoOutput.close();
            backupFile.delete();
        } catch (KryoException | IOException var7) {
            if (originalFile.exists() && !originalFile.delete()) {
                throw new PaperDbException("Couldn't clean up partially-written file " + originalFile, var7);
            } else {
                throw new PaperDbException("Couldn't save table: " + key + ". Backed up table will be used on next read attempt", var7);
            }
        }
    }

    private <E> E readTableFile(String key, File originalFile) {
        return this.readTableFile(key, originalFile, false);
    }

    private <E> E readTableFile(String key, File originalFile, boolean v1CompatibilityMode) {
        try {
            Input i = new Input(new FileInputStream(originalFile));
            Kryo kryo = this.getKryo();
            if (v1CompatibilityMode) {
                kryo.getFieldSerializerConfig().setOptimizedGenerics(true);
            }

            PaperTable<E> paperTable = (PaperTable)kryo.readObject(i, PaperTable.class);
            i.close();
            if (v1CompatibilityMode) {
                kryo.getFieldSerializerConfig().setOptimizedGenerics(false);
            }

            return paperTable.mContent;
        } catch (KryoException | ClassCastException | FileNotFoundException var7) {
            if (!v1CompatibilityMode) {
                return this.readTableFile(key, originalFile, true);
            } else if (originalFile.exists() && !originalFile.delete()) {
                throw new PaperDbException("Couldn't clean up broken/unserializable file " + originalFile, var7);
            } else {
                String errorMessage = "Couldn't read/deserialize file " + originalFile + " for table " + key;
                throw new PaperDbException(errorMessage, var7);
            }
        }
    }

    private String getDbPath(Context context, String dbName) {
        return context.getFilesDir() + File.separator + dbName;
    }

    private void assertInit() {
        if (!this.mPaperDirIsCreated) {
            this.createPaperDir();
            this.mPaperDirIsCreated = true;
        }

    }

    private void createPaperDir() {
        this.mFilesDir = this.getDbPath(this.mContext, this.mDbName);
        if (!(new File(this.mFilesDir)).exists()) {
            boolean isReady = (new File(this.mFilesDir)).mkdirs();
            if (!isReady) {
                throw new RuntimeException("Couldn't create Paper dir: " + this.mFilesDir);
            }
        }

    }

    private static boolean deleteDirectory(String dirPath) {
        File directory = new File(dirPath);
        if (directory.exists()) {
            File[] files = directory.listFiles();
            if (null != files) {
                File[] var3 = files;
                int var4 = files.length;

                for(int var5 = 0; var5 < var4; ++var5) {
                    File file = var3[var5];
                    if (file.isDirectory()) {
                        deleteDirectory(file.toString());
                    } else {
                        file.delete();
                    }
                }
            }
        }

        return directory.delete();
    }

    private File makeBackupFile(File originalFile) {
        return new File(originalFile.getPath() + ".bak");
    }

    private static boolean sync(FileOutputStream stream) {
        try {
            if (stream != null) {
                stream.getFD().sync();
            }

            return true;
        } catch (IOException var2) {
            return false;
        }
    }
}
